home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Libraries / SAT 2.3a1 / SAT Invaders sample ƒ / main.p < prev    next >
Encoding:
Text File  |  1994-11-02  |  10.2 KB  |  332 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {=============== SATInvaders main unit ================}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { SATInvaders is a very simple game demonstrating how to use the Sprite Animation}
  10. { Toolkit. It is intended as a minimal demonstration, without many features and options}
  11. { that the other sample program, HeartQuest, has. No high scores or even score, only}
  12. { one life, doesn't save settings, only one kind of enemy, no special effects like explosions}
  13. { etc. However, it is still a full Mac application with menus and event handling (using}
  14. {TransSkel). There are now some even more "minimal" demos without that.}
  15.  
  16. program SATInvaders;
  17.  
  18.     uses
  19. {$IFC UNDEFINED THINK_PASCAL}
  20.         Types, QuickDraw, Menus, {}
  21. {$ENDC}
  22.         TransSkel, SAT, GameGlobals, SoundConst, sPlayer, sEnemy, sShot, sMissile;
  23.  
  24.     var
  25.         soundFlag, plotFastFlag: Boolean;
  26.  
  27. { -------------------------------------------------------------------- }
  28. {                                Game driver procedures                                }
  29. { -------------------------------------------------------------------- }
  30.  
  31. { Setup a new level. This is called when the game starts and at each new level.}
  32.     procedure SetupLevel (level: integer);
  33.         var
  34.             i, j: integer;
  35.             sp: SpritePtr;
  36.     begin { SetupLevel }
  37.  
  38. { Clear the Sprite list! Note that this leaves the images "dead" on the screen,}
  39. { but we will soon erase them. }
  40.         while gSAT.sRoot <> nil do
  41.             SATKillSprite(gSAT.sRoot);
  42.  
  43.         missileCount := 0; { count variable in mMissile }
  44.  
  45. { Create all the enemy sprites for the level, depending on the level number. }
  46.         for i := 0 to (level + 1) do
  47.             for j := 0 to (level div 2) + 1 do
  48.                 sp := SATNewSprite(-3, i * 40 + 2, j * 40 - 40 * (level div 2 + 1), @SetupEnemy);
  49.  
  50. { Make the player sprite. }
  51.         sp := SATNewSprite(2, gSAT.offSizeH div 2, gSAT.offSizeV - 40, @SetupPlayer);
  52.  
  53. { Copy BackScreen to OffScreen to erase old sprites. }
  54.         CopyBits(gSAT.backScreen^.portbits, gSAT.offScreen^.portbits, gSAT.offScreen^.portrect, gSAT.offScreen^.portrect, srcCopy, nil);
  55.         SATRedraw;
  56.     end; { SetupLevel }
  57.  
  58. { Start a new game. Initialize level, score, number of lives, and call setuplevel to make the first level. }
  59.     procedure StartGame;
  60.     begin
  61.         level := 1;
  62.         SetupLevel(level);
  63.     end;
  64.  
  65. { Declare forward since we want to call it from MoveIt }
  66.     procedure DoFileMenu (item: integer);
  67.     forward;
  68.  
  69. { This routine is the game driver. It calls SATRun repeatedly until the game ends or is paused. }
  70. { I also read the keyboard here. This could optionally be moved to the "player object" module. }
  71.  
  72.     procedure MoveIt;
  73.         var
  74.             t: longint;
  75.             theEvent: EventRecord; { för att testa musklick }
  76.     begin
  77.         stillrunning := true; { A flag that tells whether or not to quit this routine. }
  78.  
  79. { Hide cursor and menu bar }
  80.  { NOTE: No matter how we leave the MoveIt procedure, we should ShowCursor. }
  81.         HideCursor;
  82.         SATHideMBar(gSAT.wind);
  83.         SATRedraw; {We must redraw the menu bar area. I'm lazy and redraw it all.}
  84.  
  85. { Main loop! Keep running until the game is paused or ends. }
  86.         while stillrunning = true do
  87.             begin
  88.                 t := TickCount; {Remember when we started the last turn through the loop.}
  89.  
  90. { Here is the real heart of the loop: call Animator once per loop. It will call all the objects,}
  91. { draw and erase them, sort them etc. }
  92.                 SATRun(plotFastFlag);
  93.  
  94. { All the rest of the main loop is game specific, next level, bonus handling, etc. }
  95.  
  96. {Handle the speed of the invaders. Since all move the same way, this is done globally.}
  97.                 if globalspeed.h = 0 then
  98.                     begin
  99.                         downcount := pred(downcount);
  100.                         if downcount <= 0 then
  101.                             begin
  102.                                 globalspeed.h := -lasth;
  103.                                 globalspeed.v := 0;
  104.                                 turnflag := false;
  105.                             end;
  106.                     end
  107.                 else if turnflag then
  108.                     begin
  109.                         downcount := 10;
  110.                         lasth := globalspeed.h;
  111.                         globalspeed.h := 0;
  112.                         globalspeed.v := 3;
  113.                     end;
  114.  
  115. {End of level? If so, set up a new one!}
  116.                 if not gSAT.anyMonsters then
  117.                     begin
  118.                         SATSoundShutUp;
  119.                         level := level + 1;
  120.                         SetupLevel(level);
  121.                     end; {if not anymonsters}
  122.  
  123. { Check for keys being pressed - but don't allow background processing.}
  124. { If you want background processing, either use GetNextEvent+SystemTask or WaitNextEvent (the modern call).}
  125.                 if GetOSEvent(keyDownMask, theEvent) then { keydown only }
  126.                     if BitAnd(theEvent.modifiers, cmdKey) <> 0 then {Command key pressed?}
  127.                         case char(BitAnd(theEvent.message, charCodeMask)) of {With what key?}
  128.                             'q': 
  129.                                 begin {Quit!}
  130.                                     SkelWhoa;        {Tell TransSkel to quit.}
  131. { Do all the things we have to do when we leave MoveIt! }
  132.                                     SATSoundShutUp; { Dispose of sound channel }
  133.                                     FlushEvents(EveryEvent, 0); { To forget events, like mouse clicks etc. }
  134.                                     ShowCursor;
  135.                                     SATShowMBar;
  136.                                     exit(MoveIt);
  137.                                 end;
  138.                             's': 
  139.                                 begin {Sound on/off}
  140.                                     DoFileMenu(sound);
  141.                                 end;
  142.                             otherwise
  143.                                 ; {Ignore others}
  144.                         end; { case}
  145.  
  146. { Delay, using TickCount so it doesn't matter how fast our Mac is. }
  147.                 while ((TickCount - t) < 3) do {3/60 per frame = 20 fps if possible}
  148.                     ;
  149.             end; { while stillrunning (main loop) }
  150.  
  151.         while not SATSoundDone do
  152.             SATSoundEvents; {Wait for last sound to complete}
  153.  
  154.         ShowCursor; {Balance HideCursor}
  155.         SATShowMBar;
  156.         FlushEvents(EveryEvent - DiskMask, 0); { To forget events, like mouse clicks etc. except disk events }
  157.  
  158.         ReportStr('Sorry, game over.');
  159.  
  160.         SATSoundShutUp; { Dispose of sound channel }
  161.     end; { MoveIt }
  162.  
  163.     procedure GameWindUpdate;
  164.         var
  165.             watch: CursHandle;
  166.     begin
  167. {Set the cursor to wait cursor during screen depth change test. If there's no change,}
  168. {the user won't notice.}
  169.         watch := GetCursor(WatchCursor);
  170.         SetCursor(watch^^);
  171.         if SATDepthChangeTest then
  172.             begin
  173. {Do anything needed after a screen depth change. In this demo, nothing.}
  174.             end;
  175.         ReleaseResource(Handle(watch));
  176. {Set the cursor to arrow again.}
  177.         InitCursor;
  178.  
  179. {Process the update event by redrawing the window.}
  180.         SATRedraw;
  181.  
  182. {Note: SATRedraw can be replaced by drawing with CopyBits, i.e.:}
  183. {SATSetPortScreen;}
  184. {CopyBits(offScreen^.portBits, SATwind^.portBits, offScreen^.portRect, offScreen^.portRect, srcCopy, nil);}
  185. {plus drawing borders. SATRedraw draws them black.}
  186.     end;
  187.  
  188. {    Process selection from File menu.}
  189.  
  190.     procedure DoFileMenu (item: integer);
  191.     begin
  192.         case item of
  193.             run: 
  194.                 begin
  195. { Test if we have Color QD, and if so, test bit depth! Alert if features^^.PlotFast.}
  196.                     if not ((gSAT.initDepth = 1) or (gSAT.initDepth = 4) or (gSAT.initDepth = 8)) and plotFastFlag then
  197.                         begin
  198.                             ReportStr('Please uncheck ''Fast animation'' or set the monitor to b/w, 4-bit or 8-bit mode in the Control Panel.');
  199.                             exit(DoFileMenu);
  200.                         end;
  201.                     if SATDepthChangeTest then {Update if necessary}
  202.                         ;
  203.                     StartGame;
  204.                     ShowWindow(gSAT.wind);
  205.                     SelectWindow(gSAT.wind);
  206.                     GameWindUpdate;
  207.                     MoveIt;
  208.                 end;
  209.             sound: 
  210.                 begin
  211.                     soundFlag := not soundFlag;
  212.                     CheckItem(FileMenu, sound, soundFlag);
  213.                     if soundFlag then { Tell the sound package our settings, so we don't have to bother. }
  214.                         SATSoundOn
  215.                     else
  216.                         SATSoundOff;
  217.                 end;
  218.             fastAnimation: 
  219.                 begin
  220.                     plotFastFlag := not plotFastFlag;
  221.                     CheckItem(fileMenu, fastAnimation, plotFastFlag);
  222.                 end;
  223.             quit: 
  224.                 SkelWhoa;
  225.         end;
  226.     end;
  227.  
  228.     procedure GameWindInit;
  229.     begin
  230. { Tell TransSkel to tell us when to update SATwind. }
  231.         if SkelWindow(gSAT.wind, nil, nil, @GameWindUpdate, nil, nil, nil, nil, false) then
  232.             ;
  233.  
  234. {We use SATCustomInit, so we must show the window ourselves}
  235.         ShowWindow(gSAT.wind);
  236.         SelectWindow(gSAT.wind);
  237. { Draw the contents of the window (to give the user something to look at during the rest of startup). }
  238.         SATRedraw;
  239.     end;
  240.  
  241. { -------------------------------------------------------------------- }
  242. {                        Menu handling procedures                        }
  243. { -------------------------------------------------------------------- }
  244.  
  245. {    Handle selection of "About…" item from Apple menu}
  246.  
  247.     procedure DoAbout;
  248.     begin
  249.         if Alert(aboutAlrt, nil) = 1 then
  250.             ;
  251.     end;
  252.  
  253. {    Initialize menus.  Tell TransSkel to process the Apple menu}
  254. {    automatically, and associate the proper procedures with the}
  255. {    File menu.}
  256.  
  257.     procedure SetUpMenus;
  258.     begin
  259.         SkelApple('About SAT Invaders…', @DoAbout);
  260.         fileMenu := GetMenu(fileMenuRes);
  261.         if SkelMenu(fileMenu, @DoFileMenu, nil, true) then
  262.             ;
  263. { Set the following flags so they match the menu }
  264.         soundFlag := true;
  265.         plotFastFlag := true;
  266.     end;
  267.  
  268. { Hide gamewindow on suspend, so the user can get access to disk icons etc. }
  269.  
  270.     procedure DoSuspendResume (b: boolean);
  271.     begin
  272.         if b then
  273.             begin
  274.                 ShowWindow(gSAT.wind);
  275.                 SelectWindow(gSAT.wind);
  276.             end
  277.         else
  278.             HideWindow(gSAT.wind)
  279.     end;
  280.  
  281.     function DoEvt (e: eventRecord): boolean;
  282.     begin
  283.         if e.what = OSevt then
  284.             begin
  285.                 if BAND(BROTL(e.message, 8), $FF) = SuspendResumeMessage then
  286.                     DoSuspendResume(BAnd(e.message, 1) <> 0);
  287.                 DoEvt := true;
  288.             end
  289.         else
  290.             DoEvt := false;
  291.     end; (* end DoEvent *)
  292.  
  293. { -------------------------------------------------------------------- }
  294. {                                    Main                                }
  295. { -------------------------------------------------------------------- }
  296.  
  297.     var
  298.         gameArea: Rect;
  299.  
  300. begin
  301.     SkelInit(6, nil);                { initialize }
  302.  
  303. { Init all the different parts of the game. }
  304.  
  305.     SetUpMenus;                        { install menu handlers }
  306.  
  307.     SetRect(gameArea, 0, 0, 512, 342);
  308. {We use SATCustomInit to cover the full screen INCLUDING menu bar area!}
  309.     SATCustomInit(129, 128, gameArea, nil, nil, true, true, true, true, true);
  310. {SATInit(129, 128, 512, 322);    {PICTs 129 and 128, width 512, height 322.}
  311.     GameWindInit;    { Install the game window (SATwind) in TransSkel and show it. }
  312.     Loadsounds;        { Preload all sound resources }
  313.  
  314. { Call the init routines for all the sprite units (generally to preload faces)!}
  315. { This must be done after SATInit! }
  316.     InitEnemy;
  317.     InitPlayer;
  318.     InitMissile;
  319.     InitShot;
  320.  
  321. {$IFC UNDEFINED THINK_PASCAL}
  322.     qd.randSeed := TickCount;    { Set the randseed to something that is random enough. }
  323. {$ELSEC}
  324.     randSeed := TickCount;    { Set the randseed to something that is random enough. }
  325. {$ENDC}
  326.  
  327.     SkelEventHook(@DoEvt); { Handle MultiFinder-events }
  328.  
  329.     SkelMain;                    { Loop 'til Quit selected }
  330.     SkelClobber;                { Clean up }
  331.     SATSoundShutUp;            { Terminate sounds, free the sound channel. }
  332. end.